package com.sondon.dev_soceket.tcp;

import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.Arrays;

import com.sondon.dev_soceket.business.RegisterBusiness;
import com.sondon.dev_soceket.model.Entity;
import com.sondon.dev_soceket.model.Entity_Byte;
import com.sondon.dev_soceket.tcp.util.CodeUtil;

/**
 * @Project : 硬件通讯
 * @Package : com.sondon.model
 * @Class : Entity.java
 * @Company 广州讯动网络科技有限公司
 * @Author : 蔡文锋
 * @DateTime：2015年4月2日 上午7:14:58
 * @Blog：http://blog.csdn.net/caiwenfeng_for_23
 * @Description : { TcpServer }
 */
public class TCPServer {

	private static final int BUFFER_SIZE = 1024;// 缓存大小
	private final static String HEAD = "4A79";// 包头标志

	public void Start() throws IOException {

		// 创建用于客户端连接的SocketServer实例
		@SuppressWarnings("resource")
		ServerSocket server = new ServerSocket(8877);
		
		System.out.println(server.getInetAddress().getHostAddress());
		
		while (true) {
			// 阻塞等的客户端的连接
			final Socket socket = server.accept();
			new Thread(new Runnable() {

				public void run() {
					Thread_Socket(socket);
				}
			}).start();
			;
		}
	}

	/**
	 * 
	 * @Author 蔡文锋
	 * @Data_Time 2015年4月13日 上午10:36:13
	 * @Description { 子线程socket通讯 }
	 * @param socket
	 */
	public void Thread_Socket(Socket socket) {
		boolean DeCode_Success = true; //
		int cut_count = 0;// 裁剪值 0:不裁剪 1:裁剪
		byte[] recvBuf = new byte[BUFFER_SIZE];// 接收消息的缓存
		int recvMsgSize = 0;// byte数组接收消息的大小
		int count = 0;// 接收消息的总大小
		byte[] byteMerger = new byte[0];// 接收消息byte数组合并
		try {
			// 客户端的地址信息
			// SocketAddress address = socket.getRemoteSocketAddress();
			// 获取Socket的InputStream OutputStream
			InputStream in = socket.getInputStream();
			OutputStream out = socket.getOutputStream();

			while ((recvMsgSize = in.read(recvBuf)) != -1) {
				// System.out.println("recvMsgSize  :" + recvMsgSize);
				count = count + recvMsgSize;
				byteMerger = CodeUtil.byteMerger(byteMerger, recvBuf,
						recvMsgSize);
				// 判断是否已经读完;判断数据是否完整
				if (recvMsgSize < BUFFER_SIZE && count >= 24) {
					// byte[]数组转为16进制字符串
					String recvData = CodeUtil
							.printHexString(byteMerger, count);
					// 清理字符串的空格
					recvData = recvData.replace(" ", "");
					// 解析协议
					byteMerger=	Solve_Stick_Package(recvData, out, cut_count,
							DeCode_Success);
//					byteMerger = DecodeStrData(recvData, out, cut_count,
//							DeCode_Success);
					count = byteMerger.length;
					DeCode_Success = true;
					cut_count=0;
				}
				// 清空recvBuf
				recvBuf = new byte[BUFFER_SIZE];
			}
			in.close();
			out.flush();
			out.close();
			System.out.println("关闭当前socket，开启新的socket等待连接");
			socket.close();
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}

	/**
	 * 
	 * @Author 蔡文锋
	 * @Data_Time 2015年4月8日 上午9:27:32
	 * @Description {二进制形式解析包协议}
	 * @param data
	 * @return
	 */
	public Entity_Byte DecodeByteData(byte[] data) {
		Entity_Byte eb = new Entity_Byte();
		eb.setHEAD(Arrays.copyOfRange(data, 0, 2));
		eb.setPACKNO(Arrays.copyOfRange(data, 2, 4));
		eb.setSADR(Arrays.copyOfRange(data, 4, 8));
		eb.setDADR(Arrays.copyOfRange(data, 8, 12));
		eb.setPORT(Arrays.copyOfRange(data, 12, 16));
		eb.setFLAG(Arrays.copyOfRange(data, 16, 18));
		eb.setCMD(Arrays.copyOfRange(data, 18, 20));
		eb.setLEN(Arrays.copyOfRange(data, 20, 22));
		eb.setDATA(Arrays.copyOfRange(data, 22, data.length - 2));
		eb.setCRC16(Arrays.copyOfRange(data, data.length - 2, data.length));
		return eb;
	}

	/**
	 * @Author 蔡文锋
	 * @Data_Time 2015年4月2日 上午10:21:23
	 * @Description {字符串形式解析包协议}
	 * @param data
	 * @return
	 * @throws IOException
	 */
	public byte[] DecodeStrData(String data, OutputStream out, int cut_count,
			boolean DeCode_Success) throws IOException {

		// 协议格式：Entity类
		Entity entity = new Entity();
		// 分配HEAD字段
		entity.setHEAD(data.substring(0, 4));
		// 检查包头标志： HEAD
		if (data.length() > 48 && HEAD.equals(entity.getHEAD().toUpperCase())) {
			entity.setPACKNO(data.substring(4, 8));
			entity.setSADR(data.substring(8, 16));
			entity.setDADR(data.substring(16, 24));
			entity.setPORT(data.substring(24, 32));
			entity.setFLAG(data.substring(32, 36));
			entity.setCMD(data.substring(36, 40));
			entity.setLEN(data.substring(40, 44));
			// 索引
			int index = 44 + 4 + 2 * CodeUtil.HexStringToInt(entity.getLEN());
			// 判断索引是否超出字符串长度
			if (index <= data.length()) {
				entity.setDATA(data.substring(44, index - 4));
				entity.setCRC16(data.substring(index - 4, index));

				// CRC16校验
				byte[] crc16_data = CodeUtil.hexStringToBytes(entity.getSADR()
						+ entity.getDADR() + entity.getPORT()
						+ entity.getFLAG() + entity.getCMD() + entity.getLEN()
						+ entity.getDATA());
				String crc16 = CodeUtil.CRC16Table(crc16_data);
				crc16 = crc16.substring(0, 4);
				// CRC校验，判断数据是否完整
				if (crc16.equals(entity.getCRC16())) {
					/*
					 * CRC校验通过,业务逻辑编写
					 */
					RegisterBusiness.DeCode(entity.getDATA());
					
					// System.out.println("返回响应数据包");
					out.write(entity.EnCode());

					// 裁剪一个完整的包数据
					// System.out.println("裁剪一个完整包前的data   :"+data);
					data = data.substring(index, data.length());
//					System.out.println("裁剪一个完整包后的data   :" + data);
					cut_count = 0;
					//数据完整并且校验通过
					DeCode_Success = true;
				} else {
					//数据长度足够，但CRC校验不通过
					DeCode_Success = false;
				}
			} else {
				//数据长度不够
				DeCode_Success = false;
			}
		} else {
			//数据包标志格式不对
			DeCode_Success = false;
		}

		// System.out.println("DeCode_Success   :"+DeCode_Success);
		return Solve_Stick_Package(data, out, cut_count, DeCode_Success);
	}

	/**
	 * @Author 蔡文锋
	 * @Data_Time 2015年4月2日 上午10:21:23
	 * @Description {解决粘包，包不完整等问题}
	 * @param data
	 * @param out
	 * @return
	 * @throws IOException
	 */
	public byte[] Solve_Stick_Package(String data, OutputStream out,
			int cut_count, boolean DeCode_Success) throws IOException {
//		System.out.println("包数据：  "+data);
		int HEAD_COUNT = CodeUtil.getContain_StrCount(HEAD, data);
//		System.out.println("HEAD_COUNT   :" + HEAD_COUNT);
		// 判断数据长度并且包含包头标志
		if (data.length() > 48 && HEAD_COUNT > 1) {
			data = data.substring(data.indexOf(HEAD) + 4 * cut_count  ,  data.length());
			cut_count = 1;
//			System.out.println("第二次裁剪后的data  ：" + data);
			return DecodeStrData(data, out, cut_count, DeCode_Success);
		} else if (data.length() > 0 && HEAD_COUNT < 1) {
			// data中没有包头标志，说明不是一个完整包，丢弃
			data =null;
//			System.out.println("data中没有包头标志，说明不是一个完整包，丢弃data");
			return new byte[0];
		} else if (HEAD_COUNT > 0) {//临界状态，只有一个包头标志，但数据不全等
			if ( data.length() < 48 || !DeCode_Success ) {
				// data中包含包头标志，但数据不完全
//				System.out.println("data中包含包头标志，但数据不完全    data ： " + data);
				return CodeUtil.hexStringToBytes(data);
			} else {
				// data中包含包头标志，但不肯定数据是否完全，不完全时 DeCode_Success标志为：true
//				System.out.println("data中包含包头标志，但不肯定数据是否完全  data :  "+data);
				return DecodeStrData(data, out, cut_count, DeCode_Success);
			}
		}
		return new byte[0];
	}

	public static void main(String[] args) throws IOException {
		new TCPServer().Start();
	}
}
